package com.zjmzxfzhl.modules.purchase.service.impl;

import com.zjmzxfzhl.common.util.LocalDateUtil;
import com.zjmzxfzhl.modules.purchase.controller.dto.PurchaseOrderDetailDto;
import com.zjmzxfzhl.modules.purchase.controller.dto.PurchasePaymentQueryDto;
import com.zjmzxfzhl.modules.purchase.controller.vo.MonthlyStatVo;
import com.zjmzxfzhl.modules.purchase.controller.vo.ProjectStatVo;
import com.zjmzxfzhl.modules.purchase.controller.vo.PurchaseOrderDetailVo;
import com.zjmzxfzhl.modules.purchase.controller.vo.StatTotalVo;
import com.zjmzxfzhl.modules.purchase.controller.vo.SupplierStatVo;
import com.zjmzxfzhl.modules.purchase.entity.PurchasePaymentModel;
import com.zjmzxfzhl.modules.purchase.mapper.PurchaseOrderDetailMapper;
import com.zjmzxfzhl.modules.purchase.mapper.PurchasePaymentMapper;
import com.zjmzxfzhl.modules.purchase.mapper.PurchaseProjectMapper;
import com.zjmzxfzhl.modules.purchase.mapper.PurchaseSupplierMapper;
import com.zjmzxfzhl.modules.purchase.service.PurchaseGeneralstatService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * Service
 *
 * @author yangjf
 */
@Service
public class PurchaseGeneralstatServiceImpl implements PurchaseGeneralstatService {


    public static String PAYMENT_COMPLETE = "完成";

    public static String PAYMENT_NO_PAY = "待付款";

    public static String PAYMENT_WAIT4REIMBURSEMENT = "待报销";

    @Autowired
    private PurchaseOrderDetailMapper detailMapper;

    @Autowired
    private PurchasePaymentMapper purchasePaymentMapper;

    @Autowired
    private PurchaseSupplierMapper supplierMapper;

    @Autowired
    private PurchaseProjectMapper projectMapper;

    @Override
    public StatTotalVo statTotal(String startDate, String endDate) {
        StatTotalVo statTotalVo = new StatTotalVo();
        PurchaseOrderDetailDto detailDto = new PurchaseOrderDetailDto();
        detailDto.setStartDate(startDate);
        detailDto.setEndDate(endDate);
        List<PurchaseOrderDetailVo> detailVos = detailMapper.listDetailBy(detailDto);
        BigDecimal totalAmount = new BigDecimal(0);
        if (CollectionUtils.isEmpty(detailVos)) {
            return statTotalVo;
        }

        statTotalVo.setPurchaseCount(detailVos.stream().map(PurchaseOrderDetailVo::getOrderCode).distinct().count());
        //获取合同id, 一次查询所有相关付款记录，按合同分组
        List<Long> contractIds = detailVos.stream().map(PurchaseOrderDetailVo::getContractId).distinct().collect(Collectors.toList());
        PurchasePaymentQueryDto queryDto = new PurchasePaymentQueryDto();
        queryDto.setContractIds(contractIds);
        List<PurchasePaymentModel> paymentModels = purchasePaymentMapper.listBy(queryDto);
        Map<Long, List<PurchasePaymentModel>> paymentMap = new HashMap<>(paymentModels.size());
        if (!CollectionUtils.isEmpty(paymentModels)) {
            paymentMap = paymentModels.stream().collect(Collectors.groupingBy(PurchasePaymentModel::getContractId));
        }

        //付款统计
        BigDecimal totalPaid = new BigDecimal(0);
        BigDecimal totalNonePay = new BigDecimal(0);
        BigDecimal totalWait4Reimbursement = new BigDecimal(0);
        for (PurchaseOrderDetailVo detailVo : detailVos) {
            if (detailVo.getUnitPrice() != null && detailVo.getMaterialNum() != null) {
                detailVo.setMaterialTotalPrice(detailVo.getUnitPrice().multiply(detailVo.getMaterialNum()));
                totalAmount = totalAmount.add(detailVo.getMaterialTotalPrice());

                List<PurchasePaymentModel> detailPayments = paymentMap.get(detailVo.getContractId());
                if (CollectionUtils.isEmpty(detailPayments)) {
                    //未付款
                    totalNonePay = totalNonePay.add(detailVo.getMaterialTotalPrice());
                } else {

                    for (PurchasePaymentModel paymentModel : detailPayments) {
                        String paymentSituation = paymentModel.getPaymentSituation();
                        BigDecimal paymentPrice = paymentModel.getPayAmount();
                        if (StringUtils.isEmpty(paymentSituation) || paymentSituation.contains(PAYMENT_NO_PAY)) {
                            //未付款
                            totalNonePay = totalNonePay.add(paymentPrice);
                        } else if (paymentSituation.contains(PAYMENT_COMPLETE)) {
                            totalPaid = totalPaid.add(paymentPrice);
                        } else if (paymentSituation.contains(PAYMENT_WAIT4REIMBURSEMENT)) {
                            totalPaid = totalPaid.add(paymentPrice);
                            totalWait4Reimbursement = totalWait4Reimbursement.add(paymentPrice);
                        }
                    }
                    if (totalPaid.compareTo(detailVo.getMaterialTotalPrice()) < 0) {
                        totalNonePay = totalNonePay.add(detailVo.getMaterialTotalPrice().subtract(totalPaid));
                    }
                }


            }
        }
        statTotalVo.setTotalAmount(totalAmount);
        statTotalVo.setNonPayment(totalNonePay);
        statTotalVo.setPaid(totalPaid);
        statTotalVo.setWaitForReimbursement(totalWait4Reimbursement);
        return statTotalVo;
    }

    @Override
    public List<SupplierStatVo> statSupplier(String startDate, String endDate) {
        List<SupplierStatVo> result = supplierMapper.statSupplier(startDate, endDate);
        return result;
    }

    @Override
    public List<ProjectStatVo> statProject(String startDate, String endDate) {
        List<ProjectStatVo> result = projectMapper.statProject(startDate, endDate);
        return result;
    }

    @Override
    public List<MonthlyStatVo> statPurchaseMonthly(String startDate, String endDate) {
        List<MonthlyStatVo> result = new ArrayList<>();
        PurchaseOrderDetailDto detailDto = new PurchaseOrderDetailDto();
        detailDto.setStartDate(startDate);
        detailDto.setEndDate(endDate);
        List<PurchaseOrderDetailVo> detailVos = detailMapper.listDetailBy(detailDto);
        if (CollectionUtils.isEmpty(detailVos)) {
            return result;
        }
        if (StringUtils.isEmpty(startDate)) {
            startDate = Collections.min(detailVos.stream().map(PurchaseOrderDetailVo::getOrderDate).collect(Collectors.toList()));
        }
        boolean containsEnd = false;
        if (StringUtils.isEmpty(endDate)) {
            endDate = Collections.max(detailVos.stream().map(PurchaseOrderDetailVo::getOrderDate).collect(Collectors.toList()));
            containsEnd = true;
        }
        detailVos.stream().forEach(e -> e.setOrderDate(LocalDateUtil.cutMonth(e.getOrderDate())));

        Map<String, List<PurchaseOrderDetailVo>> monthPurchaseMap = detailVos.stream().collect(Collectors.groupingBy(PurchaseOrderDetailVo::getOrderDate));

        List<String> monthSeq = LocalDateUtil.collectLocalMonths(LocalDateUtil.cutMonth(startDate), LocalDateUtil.cutMonth(endDate), containsEnd);
        if (!CollectionUtils.isEmpty(monthSeq)) {
            for (String month : monthSeq) {
                if (monthPurchaseMap.containsKey(month)) {
                    BigDecimal monthTotal = new BigDecimal(0);
                    for (PurchaseOrderDetailVo detailVo : monthPurchaseMap.get(month)) {
                        if (detailVo.getUnitPrice() != null && detailVo.getMaterialNum() != null) {
                            detailVo.setMaterialTotalPrice(detailVo.getUnitPrice().multiply(detailVo.getMaterialNum()));
                            monthTotal = monthTotal.add(detailVo.getMaterialTotalPrice());
                        }
                    }
                    Long purchaseCount = monthPurchaseMap.get(month).stream().map(PurchaseOrderDetailVo::getOrderCode).distinct().count();
                    MonthlyStatVo statVo = new MonthlyStatVo(month, monthTotal, purchaseCount);
                    result.add(statVo);
                } else {
                    result.add(new MonthlyStatVo(month, new BigDecimal(0), 0L));
                }
            }
        }
        return result;
    }


}
